package com.ruoyi.jacfile.controller;

import com.github.pagehelper.Page;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.exception.file.JacMinioException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ToolUtil;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.system.domain.JacFileInfo;
import com.ruoyi.jacfile.minio.MinIoService;
import com.ruoyi.jacfile.service.IJacFileInfoService;
import io.minio.errors.*;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.xmlpull.v1.XmlPullParserException;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

/**
 * 文件信息 提供者
 *
 * @author wjy
 * @date 2020-06-19
 */
@RestController
@RequestMapping("file")
public class JacFileInfoController extends BaseController
{

	@Autowired
	private IJacFileInfoService jacFileInfoService;

	@Autowired
	private MinIoService minIoService;

	private static final Logger log = LoggerFactory.getLogger(JacFileInfoController.class);

	/**
	 * 根据id获取文件信息
	 */
	@GetMapping("get/{fileid}")
	public JacFileInfo get(@PathVariable("fileid") Long fileid)
	{
		return jacFileInfoService.selectJacFileInfoById(fileid);

	}

	/**
	 * test
	 */
//	@GetMapping("test")
//	@Async
//	public void test() throws InterruptedException {
//
//		for(int i=0;i<3;i++) {
//			asyncTest();
//		}
//		System.out.println("1111111111111");
//	}

//	@Async
//	@GetMapping(value="test1",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
//	public Flux<String> asyncTest() throws InterruptedException {
//
//			System.out.println("..............................");
//			List<Object> list = null;
//			Flux<String> result = Flux.fromStream(IntStream.range(1, 5).mapToObj(i -> {
//				try {
//					TimeUnit.SECONDS.sleep(1);
//				} catch (InterruptedException e) {
//				}
//				return "flux data--" + i;
//			}));
//		Flux.create(t ->{
//			t.next("create1");
//			t.next("create2");
//			t.complete();
//		}).subscribe(System.out::println);
//		System.out.println("______________________________");
//			return result;
//
//	}

	private String  createStr() {
		try {
			log.info("111");
			TimeUnit.SECONDS.sleep(5);
			log.info("2222");
		} catch (InterruptedException e) {
		}
		log.info("33333");
		return "123";
//		return jacFileInfoService.selectJacFileInfoList(new JacFileInfo());
	}

	@Async
	public Future<String> doReturn(int i){
		try {
// 这个方法需要调用500毫秒
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
// 消息汇总
		return new AsyncResult<>(String.format("这个是第{%s}个异步调用的证书", i));

	}

	/**
	 * 查询文件信息列表
	 */
	@GetMapping("list")
	public R list(JacFileInfo jacFileInfo)
	{
		Page page = startReturnPage();
		List<JacFileInfo> jacFileInfos = jacFileInfoService.selectJacFileInfoList(jacFileInfo);
		if(page!=null){
			page.setTotal(2);
		}
		return result(jacFileInfos);
	}


	/**
	 * 新增保存文件信息
	 */
	@PostMapping("save")
//	@ApiOperation(value = "minio文件上传 ~", notes = "欢迎")
	public R addSave(MultipartFile file) throws InvalidPortException, InvalidEndpointException, IOException, XmlPullParserException, NoSuchAlgorithmException, RegionConflictException, InvalidKeyException, ErrorResponseException, NoResponseException, InvalidBucketNameException, InsufficientDataException, InternalException {
		minIoService.setMinioClient();
		String s = minIoService.minioUpload(file); //返回的是bucketname/encodename 的形式
		int i = s.indexOf("/");
		JacFileInfo jacFileInfo = new JacFileInfo();
		jacFileInfo.setBucketname(s.substring(0,i));
		jacFileInfo.setEncodename(s.substring(i+1));
		jacFileInfo.setRealname(file.getOriginalFilename());
		return toAjax(jacFileInfoService.insertJacFileInfo(jacFileInfo));
	}

	/**
	 * 修改保存文件信息
	 */
	@PostMapping("update")
	public R editSave(@RequestBody JacFileInfo jacFileInfo)
	{

		return toAjax(jacFileInfoService.updateJacFileInfo(jacFileInfo));
	}

	/**
	 * 删除${tableComment}
	 */
	@PostMapping("remove")
	public R remove(String ids)
	{
		return toAjax(jacFileInfoService.deleteJacFileInfoByIds(ids));
	}

	@ApiOperation(value = "minio下载 ~", notes = "欢迎")
	@GetMapping("/download/{fileid}")
//	@HasPermissions("system:file:down")
	public void fileDownload(@PathVariable("fileid") Long fileid, HttpServletResponse response, HttpServletRequest request)
	{
		JacFileInfo jacFileInfo = jacFileInfoService.selectJacFileInfoById(fileid);
		String bucketName = jacFileInfo.getBucketname();
		String encodeName = jacFileInfo.getEncodename();
		String realname = jacFileInfo.getRealname();
		try
		{
			if (!FileUtils.isValidFilename(encodeName))
			{
				throw new Exception(StringUtils.format("文件名称({})非法，不允许下载。 ", encodeName));
			}
			String filePath = ToolUtil.getDownloadPath() + encodeName;
			response.setCharacterEncoding("utf-8");
			// 下载使用"application/octet-stream"更标准
			response.setContentType("application/octet-stream");
			response.setHeader("Content-Disposition",
					"attachment;filename=" + FileUtils.setFileDownloadHeader(request, realname));
			try {
				minIoService.setMinioClient();
			} catch (Exception e) {
				throw new JacMinioException("file","minio连接失败");
			}
			minIoService.minioDownload(bucketName,encodeName,response.getOutputStream());
		}
		catch (Exception e)
		{
			log.error("下载文件失败", e);
//			return toAjax(0);
		}
//		return toAjax(1);
	}

	@ApiOperation(value = "minio上传 ~", notes = "欢迎")
	@PostMapping("/upload")
	public R upload(MultipartFile file) throws Exception {
		String s = "";
		try {
			minIoService.setMinioClient();
		} catch (Exception e) {
			throw new JacMinioException("file","minio连接失败");
		}
		try {
			s = minIoService.minioUpload(file);
		} catch (IOException e) {
			throw new Exception(StringUtils.format("上传文件({})出错，请联系管理员。 ", file.getOriginalFilename()));
		}
		int i = s.indexOf("/");
		JacFileInfo jacFileInfo = new JacFileInfo();
		jacFileInfo.setBucketname(s.substring(0,i));
		jacFileInfo.setEncodename(s.substring(i+1));
		jacFileInfo.setRealname(file.getOriginalFilename());
		return toAjax(jacFileInfoService.insertJacFileInfo(jacFileInfo));
	}

	@GetMapping("/deleteall")
	public String deleteall(JacFileInfo jacFileInfo) throws InvalidPortException, InvalidEndpointException {
		List<JacFileInfo> jacFileInfos = jacFileInfoService.selectJacFileInfoList(jacFileInfo);
		for(JacFileInfo j:jacFileInfos){
			minIoService.setMinioClient();
			minIoService.delete(j.getBucketname(),j.getEncodename());
		}
		return "删除成功";
	}

	@ApiOperation(value = "minio批量上传 ~", notes = "欢迎")
	@PostMapping("/uploads")
	public R uploads(MultipartFile[] files) throws Exception {
		List<String> errcodes = new ArrayList<>();
		int code = 0;
		try {
			minIoService.setMinioClient();
		} catch (Exception e) {
			throw new JacMinioException("file","minio连接失败");
		}
		String[] strings={};
		if(files.length>0){
			strings = new String[files.length];
			for(int i=0;i<files.length;i++){
				try {
					strings[i] = minIoService.minioUpload(files[i]);
				} catch (Exception e) {
					throw new Exception(StringUtils.format("上传文件({})出错，请联系管理员。 ", files[i].getOriginalFilename()));
				}
				String s = strings[i]; //返回的是bucketname/encodename 的形式
				int j = s.indexOf("/");
				JacFileInfo jacFileInfo = new JacFileInfo();
				jacFileInfo.setBucketname(s.substring(0,j));
				jacFileInfo.setEncodename(s.substring(j+1));
				jacFileInfo.setRealname(files[i].getOriginalFilename());
				code = jacFileInfoService.insertJacFileInfo(jacFileInfo);
				if(code <=0){
					errcodes.add(files[i].getOriginalFilename()+"上传失败 ");
				}
			}
			if(errcodes.size()==0){
				return toAjax(1);
			}
			StringBuilder stringBuilder = new StringBuilder(1024);
			for(String errcode:errcodes){
				stringBuilder.append(errcode);
			}
			throw new JacMinioException("file",stringBuilder.toString());
		}
		return toAjax(1);
	}

}
